在本地化 (localize) 專案時,我們可能會遇到需要處理金錢、價錢等貨幣的問題,在顯示價錢時我們會需要依據當前的語系顯示相對應的貨幣符號 ,例如:
<p>NT$10,000</p> // 台幣
<p>$10,000</p> // 美金
<p>¥10,000</p> // 日幣
所以今天我們要來分享的就是可以幫我們達到這件事的 Number Formatting,事實上 Number Formatting 除了貨幣以外,它也可以處理純數字格式 (decimal)、百分比 (percent) 以及物理單位 (unit) 在不同語系的顯示,因為它背後的運作原理就是透過 JS 原生的 Intl.NumberFormat 來做到的,不過我們今天的重點只會在貨幣的部分。
export default createI18n({
...,
numberFormats: {
en: {
currency: {
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
useGrouping: true
}
},
})
style
要使用的格式樣式,預設會是 decimal
currency
指定使用哪一種國際貨幣,常見的台幣 TWD, 美金 USD,詳細的完整列表可以參考 ISO 4217 。
currencyDisplay
以哪種方式顯示顯示貨幣。
minimumFractionDigits
最小的小數位數,可接受 0 到 20。
maximumFractionDigits
最大的小數位數,可接受 0 到 20,不過不能小於 minimumFractionDigits 。
useGrouping
是否使用分組分隔符,例如千/十萬/千萬分隔符。
事實上不同的 style 或多或少會有不同的屬性可以配置,不過這裡我們就只針對貨幣常使用的屬性做介紹,詳細完整的可參考 Intl.NumberFormat() constructor。
number formatting 所使用的 translation api 是 $n(value, key, locale)
value
- 要本地化的數值。key
- 這邊的 key 指是 en 下一層的 currency,這是自己定義的,不是因為 style 是 currency,因此我們也可以定義好幾個格式。locale
- 指定要用哪一個語系來本地化,預設會是全局的 locale 值。export default createI18n({
...,
numberFormats: {
en: {
currency: {
style: 'currency',
currency: 'USD'
},
currencyNoGroup: {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
useGrouping: false
}
},
})
所以在 template 的寫法會是:
<p>{{ $n(10000, 'currency') }}</p>
<p>{{ $n(10000, 'currencyNoGroup') }}</p>
得到的結果是:
<p>$10,000.00</p>
<p>$10000</p>
由於 $n 會直接回傳格式化的字串結果,我們只能作為一整體去使用,但有的時候我們會需要針對其中一部分去設定不同的樣式,例如下圖中貨幣符號和數值的大小不同,所以為了應對這種情況 vue i18n 有提供我們 NumberFormat 組件 (i18n-n
) 來達到這件事。(有點像是我昨天介紹的 Component Interpolation)
i18n-n 的基本用法如下。 (此時得到的結果和用 $n 的結果一樣)
<i18n-n tag="span" :value="100" format="currency" locale="en"></i18n-n>
i18n-n 有四個 props :
tag
選擇根節點的 HTML tag。
value
要本地化的數值。
format
選用哪一個定義好的格式的 key (同 $n(value, key) 中的 key)。
locale
指定要用哪一個語系來本地化,預設會是全局的 locale 值。
如果想要個別控制每一個部分做到上面圖示中的樣子,我們要透過 slots 的方式,像是:
<i18n-n tag="span" :value="1000" format="currency">
<template #currency="slotProps">
<span class="currency">{{ slotProps.currency }}</span>
</template>
<template #integer="slotProps">
<span class="integer">{{ slotProps.integer }}</span>
</template>
<template #group="slotProps">
<span class="group">{{ slotProps.group }}</span>
</template>
<template #fraction="slotProps">
<span class="fraction">{{ slotProps.fraction }}</span>
</template>
<template #decimal="slotProps">
<span class="decimal">{{ slotProps.decimal }}</span>
</template>
</i18n-n>
這樣得到的結果會是
// $1,000.00
<span>
<span class="currency">$</span>
<span class="integer">1</span>
<span class="group">,</span>
<span class="integer">000</span>
<span class="decimal">.</span>
<span class="fraction">00</span>
</span>
今天的分享就到這邊,如果大家對我分享的內容有興趣歡迎點擊追蹤 & 訂閱系列文章,如果對內容有任何疑問,或是文章內容有錯誤,都非常歡迎留言討論或指教的!
明天要來分享的是 Vue i18n 主題的最後一篇 Datetime Formatting,那我們明天見!
看完內容覺得 i18n 好有趣啊!
TD 是真的蠻有趣的,今天分享的[Day07] Vue i18n - Datetime Formatting 也和這篇的 Number Formatting 有差不多的感覺!
這裡程式碼排版稍微跑掉了 :p
export default createI18n({
...,
numberFormats: {
en: {
currency: {
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
useGrouping: true
}
},
})
感謝!我修正了